package com.foodost.cwpstrokes;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;

import net.youmi.android.offers.OffersManager;
import net.youmi.android.offers.PointsChangeNotify;
import net.youmi.android.offers.PointsManager;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.TextView;

import com.iflytek.cloud.speech.SpeechConstant;
import com.iflytek.cloud.speech.SpeechError;
import com.iflytek.cloud.speech.SpeechListener;
import com.iflytek.cloud.speech.SpeechSynthesizer;
import com.iflytek.cloud.speech.SpeechUser;
import com.iflytek.cloud.speech.SynthesizerListener;

public class MainActivity extends Activity implements OnClickListener,SynthesizerListener,PointsChangeNotify{
    
    private static final String TAG = MainActivity.class.getSimpleName();
    private TextView wordTextView;
    private TextView stroke1,stroke2,stroke3,stroke4;
    private TextView pinyin,countText;
    private TextView grageConentView,wordTotalContentView;
    private ImageView timerSwitch;
    private ImageView [] time = new ImageView[5];
    private CWPStrokesModel model;
    private int grage = 0;
    private List<String> hanziList;
    private int hanziIndex = 0,timeIndex = 4,count = 0;
    private String word;
    private String hyPinyin;
    private int stroke;
    private List<String> strokeList;
    private SpeechSynthesizer speechSynthesizer;
    private boolean isTimerOpen = false;
    private AlertDialog dialog;
    private Map<String,Integer> wordStrokeMap;
    
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            startTimeAnim(msg.arg1);
            if(hanziIndex < hanziList.size()){
                if(timeIndex >= 0){
                    if(msg.arg1 == 0){
                        Message msg1 = new Message();
                        msg1.what = Constants.TIME_ANIM_ACTION;
                        msg1.arg1 = timeIndex;
                        mHandler.sendMessageDelayed(msg1, 300);
                        replaceViewData();
                    }else{
                        Message msg1 = new Message();
                        msg1.what = Constants.TIME_ANIM_ACTION;
                        msg1.arg1 = msg.arg1 - 1;
                        mHandler.sendMessageDelayed(msg1, 1000);
                        
                    }
                }
            }else{
                setTimeDefaultResource();
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        setContentView(R.layout.activity_main);
        model = new CWPStrokesModel(this);
        initData();
        initView();
        SpeechUser.getUser().login(MainActivity.this, null, null, "appid=12345678", listener);
        setParam();
        initAD();
    }
    
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.d(TAG, "onNewIntent");
        initData();
        initView();
    }
    
    private SpeechListener listener = new SpeechListener(){

        @Override
        public void onCompleted(SpeechError arg0) {
            
        }

        @Override
        public void onData(byte[] arg0) {
            
        }

        @Override
        public void onEvent(int arg0, Bundle arg1) {
            
        }
        
    };
    
    private void initView(){
        wordTextView = (TextView)findViewById(R.id.wordcontent);
        pinyin = (TextView)findViewById(R.id.pinyin);
        countText = (TextView)findViewById(R.id.count);
        stroke1 = (TextView)findViewById(R.id.strokes_1);
        stroke2 = (TextView)findViewById(R.id.strokes_2);
        stroke3 = (TextView)findViewById(R.id.strokes_3);
        stroke4 = (TextView)findViewById(R.id.strokes_4);
        timerSwitch = (ImageView)findViewById(R.id.time_switch);
        time[0] = (ImageView)findViewById(R.id.time_1);
        time[1] = (ImageView)findViewById(R.id.time_2);
        time[2] = (ImageView)findViewById(R.id.time_3);
        time[3]= (ImageView)findViewById(R.id.time_4);
        time[4] = (ImageView)findViewById(R.id.time_5);
        grageConentView = (TextView)findViewById(R.id.grage_content);
        wordTotalContentView = (TextView)findViewById(R.id.wordtotal_content);
        
        stroke1.setOnClickListener(strokeClicklsn);
        stroke2.setOnClickListener(strokeClicklsn);
        stroke3.setOnClickListener(strokeClicklsn);
        stroke4.setOnClickListener(strokeClicklsn);
        wordTextView.setOnClickListener(this);
        pinyin.setOnClickListener(this);
        timerSwitch.setOnClickListener(this);
        time[0].setOnClickListener(timeClicklsn);
        time[1].setOnClickListener(timeClicklsn);
        time[2].setOnClickListener(timeClicklsn);
        time[3].setOnClickListener(timeClicklsn);
        time[4].setOnClickListener(timeClicklsn);
        hanziIndex = model.getWordIndexFromLevel(this, grage);
        Log.d(TAG, "hanziIndex = " + hanziIndex);
        getWordAndPinyin(hanziIndex);
        setWordAndPinyinText();
        strokeList = outputStrokesList(hanziIndex);
        fillStrokesTextView(strokeList);
        count = model.getWordRightCountFromLevel(this, grage);
        countText.setText(String.valueOf(count));
        
        grageConentView.setText(String.valueOf(grage+1));
        wordTotalContentView.setText(String.valueOf(hanziList.size()));
    }
    
    private void initData(){
        grage = Utils.getOrmGrage(this);
        if(model.getLevel(this, grage) == null){
            model.getHanziListByGrage(this,grage,false);
        }
        Level level = model.getLevel(this, grage);
        if(level != null){
            hanziList = Utils.StringToList(level.getHanziList());
        }
        wordStrokeMap = model.getWordStrokeMapByGrage(this, hanziList, grage);
    }
    
    private void initAD(){
        OffersManager.getInstance(this).onAppLaunch();
        PointsManager.getInstance(this).registerNotify(this);
    }
    
    public void setParam()
    {
        speechSynthesizer = SpeechSynthesizer.createSynthesizer(this);
        speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME, "nicholas");
        speechSynthesizer.setParameter(SpeechConstant.SPEED, "50");
        speechSynthesizer.setParameter(SpeechConstant.VOLUME, "100");
        speechSynthesizer.setParameter(SpeechConstant.PITCH, "50");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if(item.getItemId() == R.id.action_settings){
            Intent in = new Intent();
            in.setClass(this, SettingActivity.class);
            startActivity(in);
        }else if(item.getItemId() == R.id.action_reset){
            AlertDialog.Builder builder = new Builder(MainActivity.this);
            String content = MainActivity.this.getResources().getString(R.string.game_grage_reset_content,grage+1);
            builder.setMessage(content);
            builder.setIcon(android.R.drawable.ic_dialog_info);
            builder.setTitle(R.string.game_grage_geset_title);
            builder.setNegativeButton(R.string.ok, new DialogInterface.OnClickListener() {

             @Override
             public void onClick(DialogInterface dialog, int which) {
              dialog.dismiss();
              model.getHanziListByGrage(MainActivity.this, grage,true);
              MainActivity.this.recreate();
             }
            });
            AlertDialog dialog = builder.create();
            dialog.show();
        }
        return super.onOptionsItemSelected(item);
    }
    
    @Override
    protected void onStop() {
    	super.onStop();
    	speechSynthesizer.stopSpeaking();
    }
    
    @Override
    protected void onDestroy() {
        OffersManager.getInstance(this).onAppExit();
        PointsManager.getInstance(this).unRegisterNotify(this);
        super.onDestroy();
    }
    
    private OnClickListener timeClicklsn = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
		    if(!isTimerOpen){
		        switch(v.getId()){
		            case R.id.time_1 :
		                Utils.setTimeStartIndex(MainActivity.this, 0);
		                break;
		            case R.id.time_2 :
                        Utils.setTimeStartIndex(MainActivity.this, 1);
                        break;
		            case R.id.time_3 :
                        Utils.setTimeStartIndex(MainActivity.this, 2);
                        break;
		            case R.id.time_4 :
                        Utils.setTimeStartIndex(MainActivity.this, 3);
                        break;
		            case R.id.time_5 :
                        Utils.setTimeStartIndex(MainActivity.this, 4);
                        break;
                        default:
                            Utils.setTimeStartIndex(MainActivity.this, 4);   
		        }
		        setTimeSwitchResource();
		    }
		}
	};
    
    private OnClickListener strokeClicklsn = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			boolean flag = false;
			if(v.getId() == R.id.strokes_1){
				if(Integer.parseInt(stroke1.getText().toString()) == wordStrokeMap.get(hanziList.get(hanziIndex))){
					stroke1.setBackgroundResource(R.drawable.button_bg_right);
					flag = true;
				}else{
					stroke1.setBackgroundResource(R.drawable.button_bg_wrong);
				}
			}else if(v.getId() == R.id.strokes_2){
				if(Integer.parseInt(stroke2.getText().toString()) == wordStrokeMap.get(hanziList.get(hanziIndex))){
					stroke2.setBackgroundResource(R.drawable.button_bg_right);
					flag = true;
				}else{
					stroke2.setBackgroundResource(R.drawable.button_bg_wrong);
				}
			}else if(v.getId() == R.id.strokes_3){
				if(Integer.parseInt(stroke3.getText().toString()) == wordStrokeMap.get(hanziList.get(hanziIndex))){
					stroke3.setBackgroundResource(R.drawable.button_bg_right);
					flag = true;
				}else{
					stroke3.setBackgroundResource(R.drawable.button_bg_wrong);
				}
			}
			else if(v.getId() == R.id.strokes_4){
				if(Integer.parseInt(stroke4.getText().toString()) == wordStrokeMap.get(hanziList.get(hanziIndex))){
					stroke4.setBackgroundResource(R.drawable.button_bg_right);
					flag = true;
				}else{
					stroke4.setBackgroundResource(R.drawable.button_bg_wrong);
				}
			}
			if(flag){
				count ++;
				Log.d(TAG, "count ++ count = " + count);
				model.saveLevelWordCount(count, grage);
				countText.setText(String.valueOf(count));
				
			}
			replaceViewData();
			if(isTimerOpen){
			    mHandler.removeMessages(Constants.TIME_ANIM_ACTION);
			    Message msg = new Message();
			    msg.what = Constants.TIME_ANIM_ACTION;
			    msg.arg1 = timeIndex;
			    mHandler.sendMessage(msg);
			}
		}
	};
	
	public void replaceViewData(){
	   
	    hanziIndex =hanziIndex + 1;
		if(hanziIndex < hanziList.size()){
			wordTextView.startAnimation(setStrokeViewAnimation(wordTextView));
			model.saveLevelWordIndex(hanziIndex, grage);
		}else{
		    resetStrokesTextViewBg();
		    disenableTextView();
		    if(isTimerOpen){
		        mHandler.removeMessages(Constants.TIME_ANIM_ACTION);
		    }
		    Level levelNext = model.getLevel(this, grage + 1);
	        boolean nextIsOpen = false;
	        if(levelNext != null){
	            nextIsOpen = levelNext.isOpen();
	        }
		    if(nextIsOpen){
		        resetGameGrageData(this);
	            if(dialog != null && dialog.isShowing()){
	                dialog.dismiss();
	            }
		    }else{
		        int myPointBalance = PointsManager.getInstance(this).queryPoints();
		        float rate = (float)count/(float)hanziList.size();
		        int integral = calculateIntegral(rate);
		        if(!isTimerOpen){
		            rate = (rate > 0.65f) ? 0.65f :rate;
		            showOneGrageFinishDialog(R.string.grage_normal_str,rate,0);
		        }else if(rate < 0.8f && myPointBalance < integral){
		            showOneGrageFinishDialog(R.string.grage_failed_str,rate,0);
		        }else if(rate < 0.8f && myPointBalance > integral){
                    showOneGrageFinishDialog(R.string.grage_win_str,rate,0);
                }else{
		            showOneGrageFinishDialog(R.string.grage_win_str,rate,0); 
		        }
		        Level level = model.getLevel(this, grage);
		        if(level != null){
		            Log.d(TAG, "rate = " + rate);
		            if(level.getRate() < rate){
		                level.setRate(rate);
		                model.getFinalDb(this).update(level);
		            }
		        }
		    }
		}
		
	}
	
	public Animation setStrokeViewAnimation(View v){
        final View mV = v;
        float x = v.getPivotX();
        float y = v.getPivotY();
        int width = v.getWidth();
        int height = v.getHeight();
//        RotateAnimation rAnim = new RotateAnimation(0, 360,width/2 + x,height/2 + y);
//        rAnim.setDuration(500);
        TranslateAnimation trans = new TranslateAnimation(0, -width, y, y);
        trans.setDuration(300);
        AnimationSet animSet = new AnimationSet(false);
        animSet.addAnimation(trans);
        animSet.setAnimationListener(new Animation.AnimationListener() {
            
            @Override
            public void onAnimationStart(Animation animation) {
                
            }
            
            @Override
            public void onAnimationRepeat(Animation animation) {
                
            }
            
            @Override
            public void onAnimationEnd(Animation animation) {
            	resetStrokesTextViewBg();
                
            }
        });
        return animSet;
    }
	
	public void resetStrokesTextViewBg(){
	    if(hanziIndex < hanziList.size()){
	        getWordAndPinyin(hanziIndex);
	        setWordAndPinyinText();
	        fillStrokesTextView(outputStrokesList(hanziIndex));
	        stroke1.setBackgroundResource(R.drawable.button_bg);
	        stroke2.setBackgroundResource(R.drawable.button_bg);
	        stroke3.setBackgroundResource(R.drawable.button_bg);
	        stroke4.setBackgroundResource(R.drawable.button_bg);
	    }
	}
	
	public void disenableTextView(){
	    stroke1.setEnabled(false);
	    stroke2.setEnabled(false);
	    stroke3.setEnabled(false);
	    stroke4.setEnabled(false);
	    for(ImageView timeView : time){
	        timeView.setEnabled(false);
	    }
	    timerSwitch.setEnabled(false);
	}
	
	public void showOneGrageFinishDialog(int resId,float rate,int mIntegral){
	    AlertDialog.Builder builder = new Builder(MainActivity.this);
	    final int preIntegral = PointsManager.getInstance(MainActivity.this).queryPoints();
	    Log.d(TAG, "preIntegral = " + preIntegral);
	     int integral = calculateIntegral(rate);
	    String content = null;
	    if(rate >= 0.8f || preIntegral > integral){
	        final float aRate = rate;
	        final int aIntegral = integral;
	        if(aRate < 0.8f && preIntegral > aIntegral){
	            content = MainActivity.this.getResources().getString(resId,aIntegral);
            }else{
                content = MainActivity.this.getResources().getString(resId);
            }
            builder.setPositiveButton(R.string.next_grage, new DialogInterface.OnClickListener() {
                
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                    if(aRate < 0.8f && preIntegral > aIntegral){
                        PointsManager.getInstance(MainActivity.this).spendPoints(aIntegral);
                    }
                    resetGameGrageData(MainActivity.this);
                }
            });
	    }else if(rate >=0f && rate <0.8f){
	    	integral = integral - preIntegral;
	        content = MainActivity.this.getResources().getString(resId, integral);
	    }else if(mIntegral > 0){
	        content = MainActivity.this.getResources().getString(resId, mIntegral);
	    }
	    builder.setMessage(content);

	    builder.setTitle(R.string.grage_over);
	    builder.setNegativeButton(R.string.get_integral, new DialogInterface.OnClickListener() {

	     @Override
	     public void onClick(DialogInterface dialog, int which) {
	      dialog.dismiss();
	      OffersManager.getInstance(MainActivity.this).showOffersWall();
	     }
	    });
	    dialog = builder.create();
	    dialog.setCanceledOnTouchOutside(false);
	    if(!dialog.isShowing()){
	        dialog.show(); 
	    }
	    
	}
	
	public int calculateIntegral(float rate){
	    Level level = model.getLevel(this, grage);
	    if(level != null){
	        if(level.getRate() > rate){
	            rate = level.getRate();
	        }
	    }
	    return (int)((0.8 - rate)*400);
	}

    @Override
    public void onClick(View v) {
    	if(v.getId() == R.id.wordcontent || v.getId() == R.id.pinyin){
    		speechSynthesizer.startSpeaking(word, this);
    	}else if(v.getId() == R.id.time_switch){
    	    setTimeSwitchResource();
    	}
    }
    
    public void setTimeSwitchResource(){
        if(isTimerOpen){
            timerSwitch.setImageResource(R.drawable.clock_off);
            isTimerOpen = false;
            setTimeDefaultResource();
            mHandler.removeMessages(Constants.TIME_ANIM_ACTION);
        }else{
            timerSwitch.setImageResource(R.drawable.clock);
            isTimerOpen = true;
            timeIndex = Utils.getTimeStartIndex(this);
            if(!mHandler.hasMessages(Constants.TIME_ANIM_ACTION)){
                Message msg = new Message();
                msg.what = Constants.TIME_ANIM_ACTION;
                msg.arg1 = timeIndex;
                mHandler.sendMessage(msg);
            }
        }
    }
    
    public void getWordAndPinyin(int index){
        word = hanziList.get(index);
        String pinyin = Utils.getPinyin(word);
        if("null".equals(pinyin)){
        	hyPinyin = getResources().getString(R.string.pinyin_err);
        }else{
        	hyPinyin = pinyin;
        }
    }
    
    public void setWordAndPinyinText(){
    	wordTextView.setText(word);
        pinyin.setText(hyPinyin);
    }
    
    public List<String> outputStrokesList(int index){
        List<String> strokes = new ArrayList<String>();
        stroke = wordStrokeMap.get(hanziList.get(index));
        strokes.add(String.valueOf(stroke));
        Random random = new Random();
        for(int i = 0; i< 3; i++){
            int randomInt = random.nextInt(8) -4;
            int sum = randomInt + stroke;
            if(sum > 0 && !strokes.contains(String.valueOf(sum))){
                strokes.add(String.valueOf(sum));
            }else{
            	i--;
            }            
        }
        Collections.shuffle(strokes);
        return strokes;
    }
    
    public void fillStrokesTextView(List<String> strokeList){
    	if(strokeList.size() >= 4){
    		stroke1.setText(strokeList.get(0));
    		stroke2.setText(strokeList.get(1));
    		stroke3.setText(strokeList.get(2));
    		stroke4.setText(strokeList.get(3));
    	}
    }
    
    public void setTimeDefaultResource(){
        for(int i = 0; i < time.length; i ++){
            time[i].setImageResource(getTimeResourceId(i));
        }
    }
    
    public int getTimeResourceId(int i){
        switch(i){
        case 0:
            return R.drawable.time1;
        case 1:
            return R.drawable.time2;
        case 2:
            return R.drawable.time3;
        case 3:
            return R.drawable.time4;
        case 4:
            return R.drawable.time5;
            default:
                return R.drawable.time1;
        }
    }
    
    public void startTimeAnim(int timeIndex){
        setTimeDefaultResource();
        if(timeIndex < time.length && timeIndex >= 0){
            time[timeIndex].setImageResource(R.drawable.timeanim);
            final AnimationDrawable ad=(AnimationDrawable)time[timeIndex].getDrawable();
            ad.start();
        }
    }
    
    
	@Override
	public void onBufferProgress(int arg0, int arg1, int arg2, String arg3) {
		
	}

	@Override
	public void onCompleted(SpeechError arg0) {
		
	}

	@Override
	public void onSpeakBegin() {
		
	}

	@Override
	public void onSpeakPaused() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onSpeakProgress(int arg0, int arg1, int arg2) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onSpeakResumed() {
		// TODO Auto-generated method stub
		
	}

    @Override
    public void onPointBalanceChange(int pointsBalance) {
        int myPointBalance = PointsManager.getInstance(this).queryPoints();
        Log.v(TAG, "myPointBalance = " + myPointBalance);
        List<Level> levelList = model.getFinalDb(this).findAllByWhere(Level.class, "grage = " + (grage+1));
        Level level = null;
        int integral = 320;
        boolean nextIsOpen = false;
        if(levelList.size() > 0){
            level = levelList.get(0);
            float rate = level.getRate();
            integral = calculateIntegral(rate);
            nextIsOpen = level.isOpen();
        }
        if(nextIsOpen){
            resetGameGrageData(this);
            if(dialog != null && dialog.isShowing()){
                dialog.dismiss();
            }
        }else{
            if(myPointBalance > integral){
                PointsManager.getInstance(this).spendPoints(integral);
                resetGameGrageData(this);
                if(dialog != null && dialog.isShowing()){
                    dialog.dismiss();
                }
                
            }else if(myPointBalance < integral && (hanziIndex == hanziList.size() -1)){
                Log.d(TAG, "integral not enough");
                if(dialog != null && dialog.isShowing()){
                    dialog.dismiss();
                }
                showOneGrageFinishDialog(R.string.grage_normal_str, -1f, integral - myPointBalance);
            }
        }
    }
    
    public void resetGameGrageData(Context context){
        if(grage < 11){
            Utils.setOrmGrage(context, ++grage);
            if(model.getLevel(this, grage) == null){
                model.getHanziListByGrage(this,grage,false);
            }
            model.setGragestFromUser(context, Constants.USER, grage);
            MainActivity.this.recreate();
        }
    }

}
